﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using System.Configuration;
using System.Collections.Specialized;
using System.Data.Linq;
using System.Globalization;
using IISLogAnalyzer.Model.Entities;

namespace IISLogAnalyzer.Data.Providers
{
    public class FileLogProvider : DataProvider
    {
        private string _connectionString = string.Empty;

        public override void Initialize(string name, NameValueCollection config)
        {
            base.Initialize(name, config);

            this._connectionString = config["connectionString"];

            if (string.IsNullOrEmpty(this._connectionString))
                throw new ConfigurationErrorsException
                    ("connectionString must be set to the appropriate value");
        }

        public override List<W3CLogging> GetLogFromPeriod(DateTime startDate, DateTime endDate)
        {
            //WebLogDataContext dc = new WebLogDataContext(_connectionString);

            //var result = from w3 in dc.W3CLoggings where w3.date >= startDate && w3.date <= endDate select w3;
            
            //return result.ToList();
            throw new NotImplementedException();
        }

        public override List<W3CLogging> GetAllLogData()
        {
            List<W3CLogging> logData = new List<W3CLogging>();
            W3CLogging logRow = null;
            IEnumerable<System.IO.FileInfo> logFileList = GetFiles(_connectionString);
            char[] rowDelim = { ' ' };
            string[] logValues = null;
            CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
            string s = string.Empty; ;

            try
            {
                foreach (System.IO.FileInfo fileinfo in logFileList)
                {
                    using (System.IO.StreamReader sr = fileinfo.OpenText())
                    {
                        s = string.Empty;
                        while ((s = sr.ReadLine()) != null)
                        {
                            if (!s.StartsWith("#"))
                            {
                                // #Fields: date time s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username 
                                //c-ip cs(User-Agent) sc-status sc-substatus sc-win32-status time-taken                                       
                                logValues = s.Split(rowDelim);
                                if (logValues != null)
                                {
                                    // we have the values in array
                                    logRow = new W3CLogging();
                                    // in 2009-09-04 format
                                    logRow.date = DateTime.Parse(logValues[0], culture);
                                    logRow.time = DateTime.Parse(logValues[1], culture);
                                    logRow.s_ip = logValues[2];
                                    logRow.cs_method = logValues[3];
                                    logRow.cs_uri_stem = logValues[4];
                                    logRow.cs_uri_query = logValues[5];
                                    if (logValues[6] != string.Empty)
                                        logRow.s_port = System.Convert.ToInt16(logValues[6]);
                                    logRow.cs_username = logValues[7];
                                    logRow.c_ip = logValues[8];
                                    logRow.cs_ua = logValues[9];
                                    if (logValues[10] != string.Empty)
                                        logRow.sc_status = System.Convert.ToInt16(logValues[10]);
                                    if (logValues[11] != string.Empty)
                                        logRow.sc_substatus = System.Convert.ToInt16(logValues[11]);
                                    if (logValues[12] != string.Empty)
                                        logRow.sc_win32_status = System.Convert.ToInt16(logValues[12]);
                                    //logRow.time_taken = logValues[13];

                                    // add object to result
                                    logData.Add(logRow);
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception)
            {
                throw;
            }
            return logData;
        }

        public override int InsertLogData(List<W3CLogging> logList)
        {
            throw new NotSupportedException();
        }

        public override int InsertLogData(W3CLogging logEvent)
        {
            throw new NotSupportedException();
        }

        public override int DeleteLogData(W3CLogging logEvent)
        {
            throw new NotSupportedException();
        }

        // This method assumes that the application has discovery 
        // permissions for all folders under the specified path.
        private IEnumerable<System.IO.FileInfo> GetFiles(string path)
        {
            List<System.IO.FileInfo> files = null;

            try
            {
                string thisDay = DateTime.Today.ToString("yyMMdd");

                if (!System.IO.Directory.Exists(path))
                    throw new System.IO.DirectoryNotFoundException();

                string[] fileNames = null;
                files = new List<System.IO.FileInfo>();

                fileNames = System.IO.Directory.GetFiles(path, "*.log", System.IO.SearchOption.AllDirectories);
                foreach (string name in fileNames)
                {
                    if (!name.Contains(thisDay))  // do not try to read this days log file
                        files.Add(new System.IO.FileInfo(name));
                }
                
            }
            catch (Exception ex)
            {
                
                throw ex;
            }

            return files;
        }



        public override List<AnalyzeResult> GetDataByCip()
        {
            List<AnalyzeResult> result = new List<AnalyzeResult>();
            List<W3CLogging> logData = GetAllLogData();
            AnalyzeResult aresult = null;

            if(logData != null)
            {
                var groups = (from ld in logData 
                             where ld.sc_status == 200
                             && !ld.c_ip.Contains("192.168")
                             && !ld.c_ip.Contains("127.0.0.1")
                             group ld by ld.c_ip).Take(20);

                    foreach (var group in groups)
                    {            
                        aresult = new AnalyzeResult();
                        aresult.Value = group.Count();
                        aresult.Name = group.Key;
                        result.Add(aresult);
                    }                
            }

            var sorted = from rs in result orderby rs.Value descending select rs;

            return sorted.ToList();
        }

        public override List<AnalyzeResult> GetDataByUa()
        {
            List<AnalyzeResult> result = new List<AnalyzeResult>();
            List<W3CLogging> logData = GetAllLogData();
            AnalyzeResult aresult = null;
            string browser = string.Empty;

            if (logData != null && logData.Count > 0)
            {
                //logData = IISLogAnalyzer.Data.Providers.WebLogProvider.HelpFuncs.ResolveAllBrowserNames(logData); // Resolve all browser data

                //var groups = (from ld in logData                            
                //             where ld.sc_status == 200                             
                //             group ld by ld.cs_ua).Take(20);

                //foreach (var group in groups)
                //{
                //    aresult = new AnalyzeResult();
                //    aresult.Value = group.Count();
                //    // resolve browser
                //    //browser = ResolveBrowserName(group.Key);
                //    aresult.Name = group.Key;
                //    result.Add(aresult);
                //}
            }

            var sorted = from rs in result orderby rs.Value descending select rs;

            return sorted.ToList();
        }
        
        public override List<AnalyzeResult> GetDataByResource()
        {
            List<AnalyzeResult> result = new List<AnalyzeResult>();
            List<W3CLogging> logData = GetAllLogData();
            AnalyzeResult aresult = null;

            if (logData != null)
            {
                var groups = (from ld in logData
                             where ld.sc_status == 200
                             && !ld.cs_uri_stem.Contains(".axd")
                             && !ld.cs_uri_stem.Contains(".xml")
                             && !ld.cs_uri_stem.Contains(".css")
                             && !ld.cs_uri_stem.Contains("_top")
                             && !ld.cs_uri_stem.Contains(".js")
                             group ld by ld.cs_uri_stem).Take(20);

                foreach (var group in groups)
                {
                    aresult = new AnalyzeResult();
                    aresult.Value = group.Count();
                    aresult.Name = group.Key;
                    result.Add(aresult);
                }
            }

            var sorted = from rs in result orderby rs.Value descending select rs;

            return sorted.ToList();            
        }

        public override void GetDataPeriod(ref DateTime startDate, ref DateTime endDate)
        {
            List<W3CLogging> logData = GetAllLogData();            
            try
            {
                if (logData != null)
                {
                    startDate = logData.Min(ld => ld.date);
                    endDate = logData.Max(ld => ld.date);
                }

            }
            catch (Exception)
            {
                throw;
            }            
        }
    }
}
